package com.demo.springcloud.controller;

import com.demo.springcloud.hystrix.MyHystrixCommand;
import com.demo.springcloud.model.Users;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@RestController
public class WebController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/web/hello")
    public String hello(){
        // 逻辑省略
        // 调用SpringCloud服务提供者提供的服务
       // 加入了 ribbon 的支持，那么在调用时，即可改为使用服务名称来访问：
        // getForEntity() 发送一个HTTP GET请求，返回的ResponseEntity包含了响应体所映射成的对象
        ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://01-springcloud-service-provider/service/hello",String.class);
        String body = responseEntity.getBody();
        int statusCodeValue = responseEntity.getStatusCodeValue();
        HttpStatus statusCode = responseEntity.getStatusCode();
        HttpHeaders headers =  responseEntity.getHeaders();
        System.out.println(body);
        System.out.println(statusCodeValue);
        System.out.println(statusCode);
        System.out.println(headers);
        return restTemplate.getForEntity("http://01-springcloud-service-provider/service/hello",String.class).getBody();
        //return restTemplate.getForEntity("http://localhost:8080/service/hello",String.class).getBody();
    }


    @RequestMapping("/web/users")
    public String users(){
        // 逻辑省略
        // 调用SpringCloud服务提供者提供的服务
        // 加入了 ribbon 的支持，那么在调用时，即可改为使用服务名称来访问：
        // getForEntity() 发送一个HTTP GET请求，返回的ResponseEntity包含了响应体所映射成的对象
        ResponseEntity<Users> responseEntity = restTemplate.getForEntity("http://01-springcloud-service-provider/service/user", Users.class);
        Users body = responseEntity.getBody();
        int statusCodeValue = responseEntity.getStatusCodeValue();
        HttpStatus statusCode = responseEntity.getStatusCode();
        HttpHeaders headers =  responseEntity.getHeaders();
        System.out.println(body.getAge()+"=="+body.getId()+"=="+body.getUserName());
        System.out.println(statusCodeValue);
        System.out.println(statusCode);
        System.out.println(headers);
        return restTemplate.getForEntity("http://01-springcloud-service-provider/service/user",String.class).getBody();
        //return restTemplate.getForEntity("http://localhost:8080/service/hello",String.class).getBody();
    }

    @RequestMapping("/web/getUser")
    public Users getUser () {

        //逻辑判断（省略）

        String[] strArray = {"10001", "申来来", "21"};
        //   因为多线程环境下，使用Hashmap进行put操作会引起死循环，导致CPU利用率接近100%，所以在并发情况下不能使用HashMap
        Map<String, Object> paramMap = new ConcurrentHashMap<>();
        paramMap.put("id", 10002);
        paramMap.put("userName", "张翠山");
        paramMap.put("age", "23");


        //调用SpringCloud服务提供者提供的服务
        //ResponseEntity<User> responseEntity = restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/getUser?id={0}&name={1}&phone={2}", User.class, strArray);

        //ResponseEntity<User> responseEntity = restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/getUser?id={id}&name={name}&phone={phone}", User.class, paramMap);

        Users body1 = restTemplate.getForObject("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/getUser?id={0}&userName={1}&age={2}", Users.class, strArray);


        Users body2 = restTemplate.getForObject("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/getUser?id={id}&userName={userName}&age={age}", Users.class, paramMap);

        /*int statusCodeValue = responseEntity.getStatusCodeValue();
        HttpStatus httpStatus = responseEntity.getStatusCode();
        HttpHeaders httpHeaders = responseEntity.getHeaders();
        User body = responseEntity.getBody();

        System.out.println(statusCodeValue);
        System.out.println(httpStatus);
        System.out.println(httpHeaders);*/
        System.out.println(body1.getId() + "--" + body1.getUserName() + "--" + body1.getAge());

        System.out.println(body2.getId() + "--" + body2.getUserName() + "--" + body2.getAge());

        return restTemplate.getForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/getUser?id={id}&userName={userName}&age={age}", Users.class, paramMap).getBody();
    }


    @RequestMapping("/web/addUser")
    public Users addUser () {

        //逻辑判断（省略）

        // 要传的参数数据(很坑人的)
        MultiValueMap<String,Object> dataMap = new LinkedMultiValueMap<String,Object>();
        dataMap.add("id", "10002");
        dataMap.add("userName", "张翠山");
        dataMap.add("age", "23");

        //调用SpringCloud服务提供者提供的服务

        ResponseEntity<Users>  responseEntity = restTemplate.postForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/addUser",dataMap,Users.class);

        Users body2 = restTemplate.postForObject("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/addUser",dataMap,Users.class);

        int statusCodeValue = responseEntity.getStatusCodeValue();
        HttpStatus httpStatus = responseEntity.getStatusCode();
        HttpHeaders httpHeaders = responseEntity.getHeaders();
        Users body1 = responseEntity.getBody();

        System.out.println(statusCodeValue);
        System.out.println(httpStatus);
        System.out.println(httpHeaders);
        System.out.println(body1.getId() + "--" + body1.getUserName() + "--" + body1.getAge());

        System.out.println(body2.getId() + "--" + body2.getUserName() + "--" + body2.getAge());

        return restTemplate.postForEntity("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/getUser", dataMap,Users.class).getBody();
    }


    @RequestMapping("/web/updateUser")
    public String updateUser () {

        //逻辑判断（省略）

        // 要传的参数数据(很坑人的)
       MultiValueMap<String,Object> dataMap = new LinkedMultiValueMap<String,Object>();
        dataMap.add("id", "10002");
        dataMap.add("userName", "张翠山");
        dataMap.add("age", "23");

        Map<String, Object> paramMap = new ConcurrentHashMap<>();
        paramMap.put("id", 10002);
        paramMap.put("userName", "张翠山");
        paramMap.put("age", "23");

        //调用SpringCloud服务提供者提供的服务

       restTemplate.put("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/updateUser",dataMap);

    return "success";

    }


    @RequestMapping("/web/deleteUser")
    public String deleteUser () {

        //逻辑判断（省略）
        String[] strArray = {"10001", "申来来", "21"};

        //   因为多线程环境下，使用Hashmap进行put操作会引起死循环，导致CPU利用率接近100%，所以在并发情况下不能使用HashMap
        Map<String, Object> paramMap = new ConcurrentHashMap<>();
        paramMap.put("id", 10002);
        paramMap.put("userName", "张翠山");
        paramMap.put("age", "23");

        //调用SpringCloud服务提供者提供的服务

        restTemplate.delete("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/deleteUser?id={0}&userName={1}&age={2}",strArray);
        restTemplate.delete("http://01-SPRINGCLOUD-SERVICE-PROVIDER/service/deleteUser?id={id}&userName={userName}&age={age}",paramMap);
        return "success";

    }


    @RequestMapping("/web/hystrix")
    @HystrixCommand(fallbackMethod = "error",ignoreExceptions = Exception.class,commandProperties={@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="1500")})   //发生错误后执行error方法
    public String hystrix(){
        int a = 10/0;     // 模拟异常  除数不能为0，会抛出异常
        return restTemplate.getForEntity("http://01-springcloud-service-provider/service/hello",String.class).getBody();
    }

    // 发生错误后执行的方法
    public String error(Throwable throwable){
        System.out.println(throwable.getMessage());
        return "error";
    }


    @RequestMapping("/web/hystrix2")
    @HystrixCommand(fallbackMethod = "error",ignoreExceptions = Exception.class,commandProperties={@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="1500")})   //发生错误后执行error方法
    public String hystrix2() throws ExecutionException, InterruptedException {
        MyHystrixCommand command = new MyHystrixCommand(com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")),restTemplate);
        // 同步调用 (该方法执行后，会等待远程的返回结果，拿到了返回结果,该方法才返回,程序继续向下集成)
       // String str = command.execute();
        // 异步调用 （该方法执行后,不会立刻返回远程的结果,将来会有结果）
       Future<String> future =  command.queue();
        // 业务逻辑
       // 阻塞的方法,直到拿到结果 程序将往下执行
       String str = future.get();    // 一直等，等到拿到返回结果
        // 业务逻辑
        return str;
    }

}
